package vip.liux.backend.application.serviceImpl.pay;

import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import vip.liux.application.dots.ListResultDto;
import vip.liux.application.dots.PagedResultDto;
import vip.liux.backend.application.service.pay.AutoMapperProfile;
import vip.liux.backend.application.service.pay.PayAppService;
import vip.liux.backend.application.service.pay.PayOrderService;
import vip.liux.backend.application.service.pay.PayRefundService;
import vip.liux.backend.application.service.pay.dto.app.*;
import vip.liux.contracts.models.pay.PayApp;
import vip.liux.contracts.repositories.pay.PayAppRepository;
import vip.liux.contracts.shared.enums.Status;

import java.util.List;
import java.util.Objects;

import static vip.liux.application.PageKit.toPage;
import static vip.liux.application.PageKit.toPaged;
import static vip.liux.contracts.shared.enums.ErrorCode.*;
import static vip.liux.contracts.shared.util.ServiceExceptionUtil.exception;


/**
 * 支付应用 Service 实现类
 *
 * @author aquan
 */
@Service
@Validated
public class PayAppServiceImpl implements PayAppService {

    @Resource
    private PayAppRepository appRepo;

    @Resource
    @Lazy // 延迟加载，避免循环依赖报错
    private PayOrderService orderService;
    @Resource
    @Lazy // 延迟加载，避免循环依赖报错
    private PayRefundService refundService;

    @Override
    public Long createApp(PayAppCreateDto createDto) {
        // 验证 appKey 是否重复
        validateAppKeyUnique(null, createDto.getAppKey());

        // 插入
        PayApp app = AutoMapperProfile.INSTANCE.convert(createDto);
        appRepo.save(app);
        // 返回
        return app.getId();
    }

    @Override
    public void updateApp(Long id, PayAppUpdateDto updateDto) {
        // 校验存在
        PayApp app = validateAppExists(id);
        // 验证 appKey 是否重复
        validateAppKeyUnique(id, updateDto.getAppKey());

        // 更新
        AutoMapperProfile.INSTANCE.convert(updateDto, app);
        appRepo.save(app);
    }

    void validateAppKeyUnique(Long id, String appKey) {
        PayApp app = appRepo.findByAppKey(appKey);
        if (app == null) {
            return;
        }
        // 如果 id 为空，说明不用比较是否为相同 appKey 的应用
        if (id == null) {
            throw exception(APP_KEY_EXISTS);
        }
        if (!Objects.equals(id, app.getId())) {
            throw exception(APP_KEY_EXISTS);
        }
    }

    @Override
    public void updateAppStatus(Long id, Status status) {
        // 校验商户存在
        validateAppExists(id);
        // 更新状态
        appRepo.updateStatusById(id, status);
    }

    @Override
    public void deleteApp(Long id) {
        // 校验存在
        validateAppExists(id);
        // 校验关联数据是否存在
        if (orderService.getOrderCountByAppId(id) > 0) {
            throw exception(APP_EXIST_ORDER_CANT_DELETE);
        }
        if (refundService.getRefundCountByAppId(id) > 0) {
            throw exception(APP_EXIST_REFUND_CANT_DELETE);
        }

        // 删除
        appRepo.deleteById(id);
    }

    private PayApp validateAppExists(Long id) {
        return appRepo.findById(id)
                .orElseThrow(() -> exception(APP_NOT_FOUND));
    }

    @Override
    public PayAppDto getApp(Long id) {
        return AutoMapperProfile.INSTANCE.convert(appRepo.findById(id).orElseThrow());
    }

    @Override
    public ListResultDto<PayAppDto> getAppList(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return new ListResultDto<>();
        }
        return new ListResultDto<>(AutoMapperProfile.INSTANCE.convert(appRepo.findByIdIn(ids)));
    }

    @Override
    public ListResultDto<PayAppDto> getAppList() {
        return new ListResultDto<>(AutoMapperProfile.INSTANCE.convert(appRepo.findAll()));
    }

    @Override
    public PagedResultDto<PayAppPageItemDto> getAppPage(PayAppQueryDto pageDto) {
        return toPaged(appRepo.findByPageList(
                pageDto.getAppKey(), pageDto.getName(),
                pageDto.getStatus(), pageDto.getStart(),
                pageDto.getEnd(), toPage(pageDto)
        ).map(AutoMapperProfile.INSTANCE::pageConvert));
    }

    @Override
    public PayAppDto validPayApp(Long appId) {
        PayApp payApp = appRepo.findById(appId).orElseThrow();
        return validatePayApp(AutoMapperProfile.INSTANCE.convert(payApp));
    }

    @Override
    public PayAppDto validPayApp(String appKey) {
        PayApp payApp = appRepo.findByAppKey(appKey);
        return validatePayApp(AutoMapperProfile.INSTANCE.convert(payApp));
    }

    /**
     * 校验支付应用实体的有效性：存在 + 开启
     *
     * @param app 待校验的支付应用实体
     * @return 校验通过的支付应用实体
     */
    private PayAppDto validatePayApp(PayAppDto app) {
        // 校验是否存在
        if (app == null) {
            throw exception(APP_NOT_FOUND);
        }
        // 校验是否禁用
        if (Status.DISABLED == app.getStatus()) {
            throw exception(APP_IS_DISABLE);
        }
        return app;
    }
}
